package com.twu.biblioteca.LibraryContents;

import com.twu.biblioteca.Users.User;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by ppeter on 01/10/2014.
 */
public class Repository {
    private static Repository instance = null;

    Map<String, Book> books;
    Map<String, Movie> movies;

    private Repository() {
        books = new HashMap<String, Book>();
        movies = new HashMap<String, Movie>();
    }

    public static Repository getInstance() {
        if (instance == null) {
            instance = new Repository();
        }
        return instance;
    }

    public static Repository resetRepository() {
        instance = null;
        return getInstance();
    }

    private <T extends GenericCheckoutItem> boolean addItem(Map<String, T> map, T item) {
        if (map.containsKey(item.getId())) {
            return false;
        }
        map.put(item.getId(), item);
        return true;

    }

    public boolean addBook(Book book) {
        return addItem(this.books, book);
    }

    public boolean addMovie(Movie movie) {
        return addItem(this.movies, movie);
    }

    private List<Integer> adjustColumnLengths(List<Integer> currentWidth, List<Integer> maxWidth) {
        if (currentWidth.size() > maxWidth.size()) {
            // shortcut to get a correct sized list on the first call, could be problematic
            return currentWidth;
        }
        if (currentWidth.size() == maxWidth.size()) {
            for (int i = 0; i < maxWidth.size(); i++) {
                if (maxWidth.get(i) < currentWidth.get(i)) {
                    maxWidth.set(i, currentWidth.get(i));
                }
            }
        }
        return maxWidth;
    }

    public <T extends GenericCheckoutItem> String list(Map<String, T> map) {
        String result = "";
        List<Integer> maxColumnLengths = new ArrayList<>();

        for (T item : map.values()) {
            if (!item.isCheckedOut()) {
                maxColumnLengths = adjustColumnLengths(item.getInfoWidths(), maxColumnLengths);
            }
        }

        for (T item : map.values()) {
            if (!item.isCheckedOut()) {
                result += item.getInfo(maxColumnLengths) + "\n";
            }
        }

        if(!"".equals(result)){
            result = "-- -- --" + result +"-- -- --\n";
        }
        return result;
    }

    public void setMovies(Map<String, Movie> movies) {
        this.movies = movies;
    }

    public String listBooks() {
        return this.list(this.books);
    }

    public String listMovies() {
        return this.list(this.movies);
    }

    private <T extends GenericCheckoutItem> boolean changeItemState(Map<String, T> map, String id, boolean state, User user) {
        if (map.containsKey(id)) {
            GenericCheckoutItem relevantItem = map.get(id);
            if (relevantItem.isCheckedOut() != state) {
                relevantItem.setCheckedOut(state, user);
                return true;
            }
        }
        return false;
    }

    public boolean checkoutBook(String bookId, User user) {
        return this.changeItemState(this.books, bookId, true, user);
    }

    public boolean returnBook(String bookId) {
        return this.changeItemState(this.books, bookId, false, null);
    }

    public boolean checkoutMovie(String movieId, User user) {
        return this.changeItemState(this.movies, movieId, true, user);
    }

    public boolean returnMovie(String movieId) {
        return this.changeItemState(this.movies, movieId, false, null);
    }
}
